
import {productsFor} from "../product/products.js";
import {loadProducts} from "../network/fetcher.js";
import {MINUTE} from "../util/consts.js";
import * as utc from "../util/utc.js";
import {ø} from "../util/objects.js";
import {sharedStore} from "../framework/sharedStore.js";
import {sessionStore} from "../framework/sessionStore.js";
import {report} from "../report.js";
import {$} from "../util/seq.js";

let id = 0;
// Some hacky stuff to ensure only one download can be in progress at a time.
let downloadsInProgress = 0;
// Currently active task to auto refresh data.
let autoRefresher = NaN;

export function buildLayers(
    layerManagerAgent,
    primaryLayerAgent,
    overlayLayerAgent,
    activeLayerAgent,
    cancel,
) {
    report.status("Downloading...");
    const timerName = `build layers #${id++}`;
    const attr = ø(sharedStore.getAll(), sessionStore.getAll());
    return Promise.all(productsFor(attr)).then(products => {
        downloadsInProgress++;
        console.time(timerName);

        return loadProducts(products, cancel).then(products => {
            if (cancel.requested) {
                return;
            }
            primaryLayerAgent.submit(products[0]);
            overlayLayerAgent.submit(products[1]);
            activeLayerAgent.submit(products[1] ?? products[0]);
        }).catch(err => {
            report.error(err);
            if (cancel.requested) {
                return;
            }
            primaryLayerAgent.submit(products[0]);
            overlayLayerAgent.submit(products[1]);
            activeLayerAgent.submit(products[1] ?? products[0]);
        }).finally(() => {
            downloadsInProgress--;
            console.timeEnd(timerName);
        });

    }).finally(() => {
        // Re-download "current" data periodically.
        // UNDONE: this doesn't work for OSCAR data because the catalog is not refreshed.
        clearInterval(autoRefresher);
        autoRefresher = sharedStore.get("time_cursor") === "current" ?
            setInterval(
                () => layerManagerAgent.submit(function() {
                    return buildLayers(
                        layerManagerAgent,
                        primaryLayerAgent,
                        overlayLayerAgent,
                        activeLayerAgent,
                        this.cancel,
                    );
                }),
                30 * MINUTE) :
            NaN;
    });
}

export function defineLayerManager(
    layerManagerAgent,
    primaryLayerAgent,
    overlayLayerAgent,
    activeLayerAgent,
    sharedStore,
    sessionStore,
) {
    function downloadLayers() {
        layerManagerAgent.submit(function() {
            return buildLayers(
                layerManagerAgent,
                primaryLayerAgent,
                overlayLayerAgent,
                activeLayerAgent,
                this.cancel,
            );
        });
    }
    sharedStore.on($`change:time_cursor change:z_level change:animation_type change:overlay_type`, downloadLayers);
    sessionStore.on($`change:hd_enabled`, downloadLayers);
}

/**
 * Modifies the configuration to navigate to the chronologically next or previous data layer.
 */
export function navigate(layer, op) {
    if (downloadsInProgress > 0) {
        console.log("Download in progress--ignoring nav request.");
        return;
    }
    const next = layer?.[op]?.();
    if (next !== undefined) {
        sharedStore.set("time_cursor", utc.normalize(next));
    }
}
